/*
 * Copyright (C) 2024, Ingenic Semiconductor Co.,Ltd.
 * Author: Keven <keven.ywhan@ingenic.com>
 */

#include <common.h>

#define USEC_IN_1SEC    1000000
#define MSEC_IN_1SEC    1000

#define RISCV_CLK       (CONFIG_CPU_CLOCK_HZ)
#define CYCLES_PER_US   (RISCV_CLK / USEC_IN_1SEC)
#define CYCLES_PER_MS   (RISCV_CLK / MSEC_IN_1SEC)

#define CLINT_MSIP		0x0000
#define CLINT_MTIMECMP_L	0x4000
#define CLINT_MTIMECMP_H	0x4008
#define CLINT_MTIME_L		0xBFF8
#define CLINT_MTIME_H		0xBFFC

inline unsigned long long get_sys_mtime()
{
	unsigned long low = 0;
	unsigned long high = 0;

	do {
		high = readl(CLINT_CTRL_BASE + CLINT_MTIME_H);
		low =  readl(CLINT_CTRL_BASE + CLINT_MTIME_L);
	} while (high != readl(CLINT_CTRL_BASE + CLINT_MTIME_H));

	return ((unsigned long long)high << 32) | low;
}

inline unsigned long long get_sys_mcycle()
{
	unsigned long low = 0;
	unsigned long high = 0;

	do {
		high = read_csr(mcycleh);
		low = read_csr(mcycle);
	} while (high != read_csr(mcycleh));

	return ((unsigned long long)high << 32) | low;
}


void udelay(unsigned long udelay)
{
	unsigned long long end = get_sys_mtime() + udelay * CYCLES_PER_US;

	while (get_sys_mtime() < end);
}

void mdelay(unsigned long mdelay)
{
	while (mdelay--)
		udelay(1000);
}
